<template>
  <div class="code-view">
    <div class="code-header">
      <div class="code-header-title">{{ props.title }}</div>
      <div class="code-header-actions">
        <template v-if="props.dataHides && props.dataHides.length > 0">
          <SvgIcon
            class="iconDef"
            name="eyes"
            v-if="checkHide"
            color="#7c93b0"
            width="16"
            height="16"
            @click="handleCheckView(false)"
          />
          <SvgIcon
            class="iconDef"
            name="eyesClose"
            v-else
            color="#7c93b0"
            width="16"
            height="16"
            @click="handleCheckView(true)"
          />
        </template>
        <SvgIcon class="iconDef" name="copy" color="#7c93b0" width="16" height="16" @click="handleCopyCode" />
      </div>
    </div>
    <div class="code-content">
      <pre>{{ codeData }}</pre>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { copyTextValue } from '@/utils';
import { cloneDeep } from 'lodash';
const props = defineProps({
  title: {
    type: String,
    default: '',
  },
  // 内容
  code: {
    type: String,
    default: '',
  },
  // 可隐藏的字段
  dataHides: {
    type: Array,
    default: () => [],
  },
  // 可动态修改的字段
  dataValues: {
    type: Object,
    default: () => null,
  },
});
// 当前渲染的内容
const codeData = ref<string>('');
// 原始数据
const originCode = ref<string>('');
// 明文数据
const plaintextCode = ref<string>('');
// 按照传参排序的可隐藏字段
const forEachValues = ref<Array<string>>([]);
// 是否隐藏
const checkHide = ref<boolean>(false);
// 切换状态
const handleCheckView = (type: boolean) => {
  checkHide.value = type;
  initCode();
  forEachValues.value.forEach((item: any) => {
    item && replaceCode(item);
    initCode();
  });
};

// 用dataHides匹配code中{}内容并替换成*号
const replaceCode = (key: string) => {
  if (!props.dataValues[key]) return;
  if (props.dataHides && props.dataHides.length > 0) {
    if (checkHide.value) {
      codeData.value = codeData.value.replace('******', props.dataValues[key]);
    } else {
      const reg = new RegExp(`{${key}}`, 'g');
      codeData.value = originCode.value.replace(reg, '******');
    }
  }
};

// 匹配code中{}内容，替换为props.dataValues对应的值
const initCode = () => {
  const reg = /{(.*?)}/g;
  let match = null;
  if (!props.dataValues) plaintextCode.value = codeData.value;
  while ((match = reg.exec(codeData.value))) {
    const key = match[1];
    if (props.dataHides.includes(key)) replaceCode(key);
    if (props.dataValues[key]) {
      plaintextCode.value = plaintextCode.value.replace(`{${key}}`, props.dataValues[key]);
      codeData.value = codeData.value.replace(`{${key}}`, props.dataValues[key]);
      originCode.value = codeData.value.replace(`{${key}}`, props.dataValues[key]);
    }
  }
};

//复制明文内容
const handleCopyCode = async () => {
  copyTextValue(plaintextCode.value);
};

watch(
  () => props.dataValues,
  (newVal) => {
    if (newVal) {
      initCode();
      forEachValues.value.forEach((item: any) => {
        item && replaceCode(item);
        initCode();
      });
    }
  },
  {
    deep: true,
  },
);

watch(
  () => props.code,
  (newVal) => {
    codeData.value = cloneDeep(newVal);
    originCode.value = cloneDeep(newVal);
    plaintextCode.value = cloneDeep(newVal);
    initCode();
    forEachValues.value = [];
    if (props.dataValues) {
      Object.keys(props.dataValues).forEach((item: any) => {
        if (props.dataHides.includes(item)) {
          forEachValues.value.push(item);
          initCode();
        }
      });
    }
  },
  {
    immediate: true,
  },
);
</script>

<style lang="less" scoped>
.code-view {
  background: #ffffff;
  border: 1px solid rgba(213, 225, 247, 1);
  border-radius: 4px;
  .code-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: rgba(216, 232, 248, 0.3);
    padding: 8px 16px;
    .code-header-title {
    }
    .code-header-actions {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 10px;
      .iconDef {
        cursor: pointer;
      }
    }
  }
  .code-content {
    padding: 8px 16px;
  }

  pre {
    margin-bottom: 0;
  }
}
</style>
